package com.itheima.jdsearch.service;

import com.itheima.jdsearch.model.PageResult;
import com.itheima.jdsearch.model.SearchReq;
import com.itheima.jdsearch.pojo.GoodInfo;
import com.itheima.jdsearch.utils.ElasticUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @作者 itcast
 * @创建日期 2021/5/15 8:56
 **/
@Service
public class SearchService {

    @Autowired
    ElasticUtils<GoodInfo> elasticUtils;

    /**
     * 根据关键词 使用分词查询
     *
     * 将查询到的结果 按照分类进行分桶
     *
     * 将分桶结果收集成一个分类集合
     *
     * @param keyword
     * @return
     */
    public List<String> findCategoryListByKeyword(String keyword){
        SearchSourceBuilder builder = new SearchSourceBuilder();
//     * 根据关键词 使用分词查询
        builder.query(QueryBuilders.matchQuery("title",keyword));
//     * 将查询到的结果 按照分类进行分桶
        builder.aggregation(AggregationBuilders.terms("terms_by_category").field("category"));
//     * 将分桶结果收集成一个分类集合
        Aggregations aggregations = elasticUtils.searchAggs(builder);
        Terms termsResult = aggregations.get("terms_by_category");
        List<? extends Terms.Bucket> buckets = termsResult.getBuckets();
        if (buckets !=null && buckets.size() > 0){
            // 收集桶内每一个元素的 key 得到分类集合
            return buckets.stream().map(bucket -> bucket.getKeyAsString()).collect(Collectors.toList());
        }
        return null;
    }
    public PageResult<GoodInfo> findGoodsListByQuery(SearchReq searchReq,Integer page,Integer pageSize){
        // 构建SearchSourceBuilder条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 0. 创建bool条件，用于组合多个其它条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 1. 根据keyword 关键词  使用match   ==>  must
        boolQueryBuilder.must(QueryBuilders.matchQuery("title",searchReq.getKeyword()));
        // 2. 判断price是否为空，不为空  使用范围查询  查询价格区间  ==>  filter
        String price = searchReq.getPrice(); // 0 - 500     3000
        if(StringUtils.isNotBlank(price)){
            String[] priceArr = price.split("-");
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
            if(priceArr.length > 0){
                rangeQuery.gte(Double.valueOf(priceArr[0]));
            }
            if(priceArr.length > 1){
                rangeQuery.lt(Double.valueOf(priceArr[1]));
            }
            boolQueryBuilder.filter(rangeQuery);
        }
        // 3. 判断category是否为空，不为空  使用term查询  查询指定分类  ==>  filter
        String category = searchReq.getCategory();
        if(StringUtils.isNotBlank(category)){
            boolQueryBuilder.filter(QueryBuilders.termQuery("category",category));
        }
        builder.query(boolQueryBuilder);
        // 4.  判断sort是否为空，不为空  使用sort对应的字段进行排序，按照order属性判断是升序还是降序
        String sort = searchReq.getSort();
        if(StringUtils.isNotBlank(sort)){
            builder.sort(sort,searchReq.isOrder()? SortOrder.ASC : SortOrder.DESC);
        }
        // 5.  分页条件  按照 page  size值 设置分页
        builder.from((page - 1) * pageSize);
        builder.size(pageSize);
        // 6.  设置按照title字段高亮条件
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        builder.highlighter(highlightBuilder);
        // 7.  调用工具类执行搜索方法
        PageResult<GoodInfo> pageResult = elasticUtils.search(builder);
        // 设置页数
        Long total = pageResult.getTotal();
        if(total !=null ){
            if(total % pageSize == 0){
                pageResult.setPages(total / pageSize);
            }else {
                pageResult.setPages(total / pageSize + 1);
            }
        }
        return pageResult;
    }
}
